package com.itc.bpm.framework.listener;

import com.google.common.collect.ImmutableSet;
import com.itc.bpm.bean.BpmFormDesign;
import com.itc.bpm.bean.BpmProcessInstanceExt;
import com.itc.bpm.bean.BpmProcessTaskExt;
import com.itc.bpm.dto.DataSetDto;
import com.itc.bpm.dto.MessageDto;
import com.itc.bpm.framework.quartz.DynamicQuartzScheduler;
import com.itc.bpm.framework.quartz.TaskJob;
import com.itc.bpm.framework.websocket.WebSocketServer;
import com.itc.bpm.service.BpmFormDesignService;
import com.itc.bpm.service.BpmModelTaskCustomVariablesService;
import com.itc.bpm.service.BpmProcessInstanceExtService;
import com.itc.bpm.service.BpmProcessTaskExtService;
import com.itc.bpm.util.CronUtil;
import com.itc.bpm.util.JsonUtils;
import com.itc.common.core.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.flowable.bpmn.model.Task;
import org.flowable.bpmn.model.UserTask;
import org.flowable.common.engine.api.delegate.event.FlowableEngineEntityEvent;
import org.flowable.common.engine.api.delegate.event.FlowableEngineEventType;
import org.flowable.engine.HistoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.delegate.event.AbstractFlowableEngineEventListener;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.identitylink.api.IdentityLink;
import org.flowable.identitylink.api.IdentityLinkInfo;
import org.flowable.task.service.delegate.DelegateTask;
import org.flowable.task.service.impl.persistence.entity.TaskEntity;
import org.flowable.task.service.impl.persistence.entity.TaskEntityImpl;
import org.quartz.JobDataMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 任务监听类 实现任务的执行生命周期管理
 * @author yl
 */
@Component
@Slf4j
public class BpmTaskEventListener extends AbstractFlowableEngineEventListener {


    @Autowired
    WebSocketServer webSocketServer;

    @Autowired
    BpmProcessTaskExtService bpmProcessTaskExtService;

    @Autowired
    BpmModelTaskCustomVariablesService bpmModelTaskCustomVariablesService;
    @Autowired
    DynamicQuartzScheduler dynamicQuartzScheduler;

    @Autowired
    BpmFormDesignService bpmFormDesignService;

    @Autowired
    BpmProcessInstanceExtService bpmProcessInstanceExtService;

    @Autowired
    RuntimeService historyService;

    public static final Set<FlowableEngineEventType> TASK_EVENTS = ImmutableSet.<FlowableEngineEventType>builder()
            .add(FlowableEngineEventType.TASK_CREATED)
            //.add(FlowableEngineEventType.TASK_ASSIGNED) //任务领取主动配置了审批人信息，不用监听操作
            .add(FlowableEngineEventType.TASK_COMPLETED) // 由于审批通过时，已经记录了 task 的 status 为通过，所以不需要监听了。
            //.add(FlowableEngineEventType.ACTIVITY_CANCELLED)
            .build();

    public BpmTaskEventListener(){
        super(TASK_EVENTS);
    }
    //创建执行
    @Override
    protected void taskCreated(FlowableEngineEntityEvent event) {
       // 设置候选人
        TaskEntityImpl task = (TaskEntityImpl) event.getEntity();
        BpmProcessTaskExt taskExt = new BpmProcessTaskExt();
        taskExt.setProcessInstanceId(task.getProcessInstanceId());
        taskExt.setTaskId(task.getId());
        taskExt.setTaskName(task.getName());
        taskExt.setCategory(task.getCategory());
        ProcessInstance historicProcessInstance = historyService.createProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult();
        Map<String,Object> stringStringMap =  historicProcessInstance.getProcessVariables();
        //historicProcessInstance.ge
        // String modelId = task.get("modelId")+"";
        Map<String,String> variables = bpmModelTaskCustomVariablesService.getTaskVariables(task.getProcessDefinitionId(),task.getTaskDefinitionKey());
        // 获取任务候选人 处理人席位
        taskExt = validateVaribles(taskExt,variables);
        if(StringUtils.isNotEmpty(taskExt.getFormCode())){
            BpmFormDesign bpmFormDesign = bpmFormDesignService.findCurrentForm(taskExt.getFormCode());
            if(bpmFormDesign!=null){
                taskExt.setFormId(bpmFormDesign.getId());
            }
        }
        taskExt.setProcessDefinitionId(task.getProcessDefinitionId());
        taskExt.setStatus(0);
        //taskExt.setCreateTime(LocalDateTime.now());
        // 记录任务信息
        bpmProcessTaskExtService.save(taskExt);
        //发送待领取消息提醒
        MessageDto messageDto = new MessageDto();
        messageDto.setTaskName(task.getName());
        messageDto.setTaskId(task.getId());
        messageDto.setType(0);
        messageDto.setDate(LocalDateTime.now());
        messageDto.setProcessInstanceId(task.getProcessInstanceId());
        //BpmProcessInstanceExt bpmProcessInstanceExt= bpmProcessInstanceExtService.getProcessInstanceExtByInstanceId(task.getProcessInstanceId());
        if(stringStringMap.containsKey("modelId")){
            messageDto.setModelId(stringStringMap.get("modelId")+"");
        }
        if(stringStringMap.containsKey("instanceName")){
            messageDto.setProcessInstanceName(stringStringMap.get("instanceName")+"");
        }
        // 创建时候响应时长不为空，则创建定时任务定时检查 任务是否执行
        if(taskExt.getResponseTime()!=null){
            long fiveMinutesInMillis =  taskExt.getResponseTime() * 60 * 1000; // 计算getResponseTime分钟的毫秒数
            Date startTime = new Date(); // 现在的时间
            startTime.setTime(startTime.getTime() + fiveMinutesInMillis); // 五分钟后的时间
            String cron = "0 0/"+taskExt.getResponseTime()+" * * * ?";
            JobDataMap jobDataMap = new JobDataMap();
            jobDataMap.put("taskId",task.getId());
            jobDataMap.put("noticeType","1");
            jobDataMap.put("taskName",taskExt.getTaskName());
            jobDataMap.put("candidateUsers",taskExt.getCandidateUsers());
            dynamicQuartzScheduler.addJob(task.getId(),task.getId(), TaskJob.class,startTime,null,cron,jobDataMap);
        }
        try {
            webSocketServer.sendInfo(JsonUtils.objectToJson(messageDto),taskExt.getCandidateUsers());
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }

    @Override
    protected void taskCompleted(FlowableEngineEntityEvent event) {
        System.out.println(event.getType().name());
        super.taskCompleted(event);

    }

    /**
     *  封装处理任务参数
     * @param taskExt
     * @param variables
     * @return
     */
    public BpmProcessTaskExt validateVaribles(BpmProcessTaskExt taskExt,Map<String,String> variables){
        if(variables.containsKey("dealManagePosition") && StringUtils.isNotEmpty(variables.get("dealManagePosition"))){
            String del = variables.get("dealManagePosition");
            del = del.replace("[","");
            del = del.replace("]","");
            taskExt.setCandidateUsers(del);
        }else if(variables.containsKey("dataSet") && StringUtils.isNotEmpty(variables.get("dataSet"))){
            String json = variables.get("dataSet");
            try {
                List<DataSetDto> dataSetDtos = JsonUtils.jsonToList(json, DataSetDto.class);
                String depts = null;
                for(DataSetDto dto:dataSetDtos){
                    if(CollectionUtils.isNotEmpty(dto.getDepts())){
                        String result = dto.getDepts().stream().collect(Collectors.joining(","));
                        if(StringUtils.isNotEmpty(depts)){
                            depts = depts+","+result;
                        }else{
                            depts = result;
                        }
                    }
                }
                taskExt.setCandidateUsers(depts);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if(variables.containsKey("isRepeatComplete")){
            taskExt.setIsRepeatComplete(variables.get("isRepeatComplete")!=null?Integer.parseInt(variables.get("isRepeatComplete")):0);
        }
        if(variables.containsKey("formCode")){
            taskExt.setFormCode(variables.get("formCode"));
        }
        if(variables.containsKey("dealTime")){
            taskExt.setDealTime(variables.get("dealTime")!=null?Integer.parseInt(variables.get("dealTime")):null);
        }
        if(variables.containsKey("responseTime")){
            taskExt.setResponseTime(variables.get("responseTime")!=null?Integer.parseInt(variables.get("responseTime")):null);
        }
        if(variables.containsKey("spaceTime")){
            taskExt.setSpaceTime(variables.get("spaceTime")!=null?Integer.parseInt(variables.get("spaceTime")):null);
        }
        if(variables.containsKey("isFinishRepeat")){
            taskExt.setIsFinishRepeat(variables.get("isFinishRepeat")!=null?Integer.parseInt(variables.get("isFinishRepeat")):null);
        }
        if(variables.containsKey("isCirculate")){
            taskExt.setIsCirculate(variables.get("isCirculate")!=null?Integer.parseInt(variables.get("isCirculate")):null);
        }
        if(variables.containsKey("isNoteMessage")){
            taskExt.setIsNoteMessage(variables.get("isNoteMessage")!=null?Integer.parseInt(variables.get("isNoteMessage")):null);
        }
        return taskExt;
    }


}
